package com.vladium.utils;

// ----------------------------------------------------------------------------
/**
 * The main interface for exploring an object profile tree. See individual
 * methods for details.
 * 
 * @see ObjectProfiler#profile(Object)
 * @author (C) <a
 *         href="http://www.javaworld.com/columns/jw-qna-index.shtml">Vlad
 *         Roubtsov</a>, 2003
 */
public interface IObjectProfileNode {
	// public: ................................................................
	/**
	 * A generic interface for defining node filters. A node filter is used as a
	 * guard to determine whether a given visitor should be given a shot as
	 * doing something with a profile tree node.
	 */
	interface INodeFilter {
		/**
		 * @param node
		 *            about to be visited [never null]
		 * @return 'true' if 'node' and its children should be visited
		 */
		boolean accept(IObjectProfileNode node);
	} // end of nested interface

	/**
	 * A generic interface for defining node visitors. A node visitor is applied
	 * to a profile tree node both before and after visiting the node's
	 * children, if any.
	 */
	interface INodeVisitor {
		/**
		 * Pre-order visit.
		 * 
		 * @param node
		 *            being visited [never null]
		 */
		void previsit(IObjectProfileNode node);

		/**
		 * Post-order visit.
		 * 
		 * @param node
		 *            being visited [never null]
		 */
		void postvisit(IObjectProfileNode node);
	} // end of nested interface

	/**
	 * Returns the object associated with this node. This is never null except
	 * for shell pseudo-nodes.
	 * 
	 * @return object instance [null only for shell nodes]
	 */
	Object object();

	/**
	 * Returns a human-readable name for this node, usually derived from the
	 * class field or array index that was used to reach the {@link #object()
	 * object} associated with this node.
	 * 
	 * @return node name [never null]
	 */
	String name();

	int getModifiers();

	/**
	 * Returns the full size (in bytes) assigned to this node in its profile
	 * tree. This is the sum of sizes of the node class's {@link #shell() shell}
	 * and its non-primitive non-null {@link #children() instance fields},
	 * computed as a closure over the spanning tree produced by
	 * {@link ObjectProfiler#profile}.
	 * 
	 * @return total node size [always positive]
	 */
	int size();

	/**
	 * Returns the reference count for the associated {@link #object()}. This is
	 * exactly the number of unique references to this object in the object
	 * graph submitted to {@link ObjectProfiler#profile}.
	 * 
	 * @return reference count [always positive]
	 */
	int refcount();

	/**
	 * Returns the assigned ownership parent for this node. This is null for the
	 * root node.
	 * 
	 * @return parent node [null only for the root node]
	 */
	IObjectProfileNode parent();

	/**
	 * Returns all children of this node. These are non-null references found in
	 * this object's class fields (or array slots if the object is of an array
	 * type). The result is sorted in decreasing {@link #size() size} order.
	 * <P>
	 * Note: the returned array also contains the {@link #shell() shell}
	 * pseudo-node.
	 * 
	 * @return array of children nodes, sorted by size [never null, may be
	 *         empty]
	 */
	IObjectProfileNode[] children();

	/**
	 * Returns the shell pseudo-node for this node. This represents all instance
	 * data fields that are "inlined" in the class definition represented by
	 * this node (including all superclasses all the way to java.lang.Object).
	 * This includes primitive data fields, object references representing
	 * non-primitive fields, and (for arrays) the array length field and storage
	 * required for the array slots.
	 * <P>
	 * Another way to describe this is that node.shell().size() is the minimum
	 * size an instance of node.object().getClass() can be (when all
	 * non-primitive instance fields are set to 'null').
	 * <P>
	 * The returned reference is also guaranteed to be present somewhere in the
	 * array returned by {@link #children()}. This data is kept in a separate
	 * node instance to simplify tree visiting and node filtering.
	 * 
	 * @return shell pseudo-node [null only for shell nodes]
	 */
	IObjectProfileNode shell();

	/**
	 * Returns the full path from the profile tree root to this node, in that
	 * direction. The result includes the root node as well as the current node.
	 * <P>
	 * Invariant: node.root() == node.path()[0] Invariant:
	 * node.path()[node.path().length - 1] == node Invariant: node.path().length
	 * == node.pathlength()
	 * 
	 * @return node tree path [never null/empty]
	 */
	IObjectProfileNode[] path();

	/**
	 * A convenience method for retrieving the root node from any node in a
	 * profile tree.
	 * <P>
	 * Invariant: node.root() == node iff 'node' is the root of its profile tree
	 * Invariant: node.root() == node.path()[0]
	 * 
	 * @return the root node for the profile tree that the current node is a
	 *         part of [never null]
	 */
	IObjectProfileNode root();

	/**
	 * A convenience method for retrieving this node's tree path length.
	 * 
	 * @return path length [always positive]
	 */
	int pathlength();

	/**
	 * A generic hook for traversing profile trees using {@link INodeFilter
	 * filters} and {@link INodeVisitor visitors}. See
	 * IObjectProfileNode.INodeFilter and IObjectProfileNode.INodeVisitor for
	 * more details
	 * 
	 * @param filter
	 *            [null is equivalent to no filtering]
	 * @param visitor
	 *            [may not be null]
	 * @return 'true' iff either 'filter' was null or it returned 'true' for
	 *         this node
	 */
	boolean traverse(INodeFilter filter, INodeVisitor visitor);

	/**
	 * Dumps this node into a flat-text format used by the
	 * {@link ObjectProfileVisitors#newDefaultNodePrinter()} default node
	 * visitor.
	 * 
	 * @return indented dump string [could be very large]
	 */
	String dump();
} // end of interface
// ----------------------------------------------------------------------------
